package hos.thread.executor

import android.util.Log
import hos.thread.PriorityRunnable
import hos.thread.RunnableThis
import hos.thread.ThreadOption
import hos.thread.hander.MH
import java.util.concurrent.PriorityBlockingQueue
import java.util.concurrent.ThreadFactory
import java.util.concurrent.ThreadPoolExecutor
import java.util.concurrent.TimeUnit
import java.util.concurrent.atomic.AtomicInteger
import kotlin.math.max
import kotlin.math.min

/**
 * <p>Title: ThreadExecutor </p>
 * <p>Description:  </p>
 * <p>Company: www.mapuni.com </p>
 *
 * @author : 蔡俊峰
 * @date : 2023/8/4 21:46
 * @version : 1.0
 */
class ThreadExecutor private constructor(
    cpuCount: Int = Runtime.getRuntime().availableProcessors(),
) : ThreadPoolExecutor(
    max(4, min(cpuCount + 1, 5)),
    cpuCount * 2 + 1,
    30L, TimeUnit.SECONDS,
    PriorityBlockingQueue<Runnable>(),
    object : ThreadFactory {
        private val threadId by lazy { AtomicInteger(0) }
        override fun newThread(r: Runnable?): Thread {
            return Thread(r, String.format("hos_io_%d", threadId.getAndIncrement()))
        }
    }
) {

    companion object {

        @JvmStatic
        val thread by lazy {
            get()
        }

        @JvmStatic
        @Synchronized
        private fun get(): ThreadExecutor {
            return ThreadExecutor()
        }

        @JvmStatic
        @JvmOverloads
        fun run(
            job: ThreadOption.Job = ThreadOption.Job.ON,
            priority: Int = 0,
            block: ThreadExecutor.() -> Unit,
        ) = thread.start(job, priority, block)

        @JvmStatic
        fun isMainThread(): Boolean {
            return MH.isMainThread()
        }

    }

    override fun afterExecute(r: Runnable?, t: Throwable?) {
        //监控线程池耗时任务,线程创建数量,正在运行的数量
        Log.d("Thread: ", "activeCount:$activeCount")
        Log.d("Thread: ", "ThreadName" + Thread.currentThread().name)
        if (r is PriorityRunnable) {
            Log.d("Thread: ", "已执行完的任务的优先级是" + r.priority)
        }
    }

    fun postIo(priority: Int = 0, runnable: Runnable): ThreadExecutor {
        execute(PriorityRunnable(priority, runnable))
        return this
    }

    /**
     * 运行在工作线程
     *
     * @param runnable 工作线程
     */
    fun postIo(runnable: Runnable): ThreadExecutor {
        return postIo(0, runnable)
    }

    /**
     * 运行在工作线程
     *
     * @param runnable 工作线程
     */
    fun postOnIo(runnable: Runnable): ThreadExecutor {
        if (MH.isMainThread()) {
            postIo(runnable)
        } else {
            runnable.run()
        }
        return this
    }

    @JvmOverloads
    fun start(
        job: ThreadOption.Job = ThreadOption.Job.ON,
        priority: Int = 0,
        block: ThreadExecutor.() -> Unit,
    ): ThreadExecutor {
        if (job == ThreadOption.Job.TO) {
            return postIo(priority,RunnableThis {
                try {
                    block.invoke(this)
                } finally {
                    remove(it)
                }
            })
        }
        return postOnIo(RunnableThis {
            try {
                block.invoke(this)
            } finally {
                remove(it)
            }
        })
    }
}